home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / oldwish / old / wishSelect.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-10-03  |  16.4 KB  |  624 lines

  1. /* 
  2.  * fsflatSelect.c --
  3.  *
  4.  *    Routines for selection of listed files and groups.
  5.  *
  6.  * Copyright 1987 Regents of the University of California
  7.  * All rights reserved.
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: fsflatSelect.c,v 1.1 88/10/03 12:48:42 mlgray Exp $ SPRITE (Berkeley)";
  19. #endif not lint
  20.  
  21.  
  22. #include "sx.h"
  23. #include "string.h"
  24. #include "fsflatInt.h"
  25.  
  26. /*
  27.  * Forward references for procedures defined below.
  28.  */
  29. extern    void    FsflatSelChange();
  30. extern    int    FsflatSelFetch();
  31.  
  32.  
  33. /*
  34.  *----------------------------------------------------------------------
  35.  *
  36.  * FsflatChangeSelection --
  37.  *
  38.  *    Change the selection variable.
  39.  *
  40.  * Results:
  41.  *    None.
  42.  *
  43.  * Side effects:
  44.  *    The selection variable is modified.
  45.  *
  46.  *----------------------------------------------------------------------
  47.  */
  48. void
  49. FsflatChangeSelection(aWindow, clientData, fileP, lineP, addToP)
  50.     FsflatWindow    *aWindow;
  51.     ClientData        clientData;
  52.     Boolean        fileP;    /* selecting a file or a group? */
  53.     Boolean        lineP;    /* select a whole line, or just file name? */
  54.     Boolean        addToP;    /* just change sel. status of one entry */
  55. {
  56.     FsflatFile    *filePtr;
  57.     FsflatGroup    *groupPtr;
  58.     FsflatSelection    *selPtr, *backPtr;
  59.  
  60.     if (fileP) {
  61.     filePtr = (FsflatFile *) clientData;
  62.     } else {
  63.     groupPtr = (FsflatGroup *) clientData;
  64.     }
  65.  
  66.     if (lineP) {
  67.     Sx_Notify(fsflatDisplay, aWindow->surroundingWindow, -1, -1, 0,
  68.         "Line-mode selection temporarily disabled.",
  69.         NULL, TRUE, "Continue", (char *) NULL);
  70.     return;
  71.     }
  72.     
  73.     if (fileP) {
  74.     if (!addToP) {
  75.         if (filePtr->selectedP && !lineP) {
  76.         FsflatClearWholeSelection(aWindow);
  77.         return;
  78.         } else {        /* make the new selection */
  79.         /* check if it's already selected and needs lineP changed. */
  80.         if (filePtr->selectedP == TRUE) {
  81. #ifdef NOTDEF
  82.             for (selPtr = aWindow->selectionList; selPtr != NULL;
  83.                 selPtr = selPtr->nextPtr) {
  84.             if (selPtr->selected.filePtr == filePtr) {
  85.                 break;
  86.             }
  87.             }
  88.             if (selPtr == NULL) {
  89.             sprintf(fsflatErrorMsg, "%s%s%s", "The selected file `",
  90.                 filePtr->name,
  91.                 "' couldn't be found on the selection list.");
  92.             Sx_Panic(fsflatDisplay, fsflatErrorMsg);
  93.             }
  94.             filePtr->lineP = lineP;
  95.             selPtr->lineP = lineP;
  96.             FsflatRedrawFile(aWindow, filePtr);
  97.             return;
  98. #endif NOTDEF
  99.         }
  100.         /* new selection */
  101.         FsflatClearWholeSelection(aWindow);
  102.         /*
  103.          * After the first time, Sx_SelectionSet will call
  104.          * FsflatSelChange, which calls FsflatClearWholeSelection().
  105.          * This is a warning...
  106.          */
  107.         Sx_SelectionSet(fsflatDisplay, FsflatSelFetch, FsflatSelChange,
  108.             (ClientData) aWindow);
  109.         Tcl_SetVar(aWindow->interp, "sel", filePtr->name, 1);
  110.         Tcl_SetVar(aWindow->interp, "selection", filePtr->name, 1);
  111.         filePtr->selectedP = TRUE;
  112.         selPtr = (FsflatSelection *)
  113.             malloc(sizeof (FsflatSelection));
  114.         selPtr->fileP = TRUE;
  115.         selPtr->selected.filePtr = filePtr;
  116.         selPtr->nextPtr = NULL;
  117.         if (lineP) {
  118.             filePtr->lineP = TRUE;
  119.             selPtr->lineP = TRUE;
  120.         } else {
  121.             selPtr->lineP = FALSE;
  122.         }
  123.         if (aWindow->selectionList != NULL) {
  124.             sprintf(fsflatErrorMsg,
  125.                 "Selection list should have been null and wasn't.");
  126.             Sx_Panic(fsflatDisplay, fsflatErrorMsg);
  127.         }
  128.         aWindow->selectionList = selPtr;
  129.         FsflatRedrawFile(aWindow, filePtr);
  130.         }
  131.         return;
  132.     }
  133.     /* addToP is TRUE */
  134.     if (filePtr->selectedP && !lineP) {
  135.         char    *tclSel;
  136.         char    *removeEntry;
  137.  
  138.         filePtr->selectedP = FALSE;
  139.         filePtr->lineP = FALSE;
  140.         tclSel = Tcl_GetVar(aWindow->interp, "sel", 1);
  141.         if (tclSel == NULL) {
  142.         sprintf(fsflatErrorMsg, "Tcl selection variable wasn't found.");
  143.         Sx_Panic(fsflatDisplay, fsflatErrorMsg);
  144.         }
  145.         removeEntry = (char *) malloc(strlen(tclSel) + 1);
  146.         removeEntry[0] = '\0';
  147.         /* remove it from selection */
  148.         for (selPtr = aWindow->selectionList, backPtr = selPtr;
  149.             selPtr != NULL; selPtr = selPtr->nextPtr) {
  150.         if (!selPtr->fileP) {
  151.             backPtr = selPtr;
  152.             continue;
  153.         }
  154.         if (selPtr->selected.filePtr != filePtr) {
  155.             strcat(removeEntry, filePtr->name);
  156.             strcat(removeEntry, " ");
  157.             backPtr = selPtr;
  158.             continue;
  159.         }
  160.         /* check if nothing is selected anymore */
  161.         if (selPtr == aWindow->selectionList) {
  162.             aWindow->selectionList = selPtr->nextPtr;
  163.         } else {
  164.             backPtr->nextPtr = selPtr->nextPtr;
  165.         }
  166.         free(selPtr);
  167.         FsflatRedrawFile(aWindow, filePtr);
  168.         break;
  169.         }
  170.         if (removeEntry[strlen(removeEntry) - 1] == ' ') {
  171.         removeEntry[strlen(removeEntry) - 1] = '\0';
  172.         }
  173.         Tcl_SetVar(aWindow->interp, "sel", removeEntry, 1);
  174.         Tcl_SetVar(aWindow->interp, "selection", removeEntry, 1);
  175.         free(removeEntry);
  176.     } else {
  177.         char    *tclSel;
  178.         char    *addEntry;
  179.  
  180.         /* add it to selection */
  181.         /* check if it's already selected and needs lineP changed. */
  182.         if (filePtr->selectedP == TRUE) {
  183. #ifdef NOTDEF
  184.         for (selPtr = aWindow->selectionList; selPtr != NULL;
  185.             selPtr = selPtr->nextPtr) {
  186.             if (selPtr->selected.filePtr == filePtr) {
  187.             break;
  188.             }
  189.         }
  190.         if (selPtr == NULL) {
  191.             sprintf(fsflatErrorMsg, "%s%s%s", "The selected file `",
  192.                 filePtr->name,
  193.                 "' couldn't be found on the selection list.");
  194.             Sx_Panic(fsflatDisplay, fsflatErrorMsg);
  195.         }
  196.         filePtr->lineP = lineP;
  197.         selPtr->lineP = lineP;
  198.         FsflatRedrawFile(aWindow, filePtr);
  199.         return;
  200. #endif NOTDEF
  201.         }
  202.         /* add new selection */    
  203.         filePtr->selectedP = TRUE;
  204.         if (lineP) {
  205.         filePtr->lineP = TRUE;
  206.         }
  207.         selPtr = (FsflatSelection *) malloc(sizeof (FsflatSelection));
  208.         selPtr->fileP = TRUE;
  209.         if (lineP) {
  210.         selPtr->lineP = TRUE;
  211.         } else {
  212.         selPtr->lineP = FALSE;
  213.         }
  214.         selPtr->nextPtr = NULL;
  215.         selPtr->selected.filePtr = filePtr;
  216.         if (aWindow->selectionList == NULL) {
  217.         /*
  218.          * After the first time, Sx_SelectionSet will call
  219.          * FsflatSelChange, which calls FsflatClearWholeSelection().
  220.          * This is a warning...
  221.          */
  222.         Sx_SelectionSet(fsflatDisplay, FsflatSelFetch, FsflatSelChange,
  223.             (ClientData) aWindow);
  224.         aWindow->selectionList = selPtr;
  225.         } else {
  226.         for (backPtr = aWindow->selectionList; backPtr->nextPtr != NULL;
  227.             backPtr = backPtr->nextPtr) {
  228.             /* do nothing */
  229.         }
  230.         backPtr->nextPtr = selPtr;
  231.         }
  232.         tclSel = Tcl_GetVar(aWindow->interp, "sel", 1);
  233.         /* space for 2 strings, blank between and null char */
  234.         addEntry = (char *) malloc(strlen(tclSel) +
  235.             strlen(filePtr->name + 2));
  236.         addEntry[0] = '\0';
  237.         strcat(addEntry, tclSel);
  238.         strcat(addEntry, " ");
  239.         strcat(filePtr->name, tclSel);
  240.         Tcl_SetVar(aWindow->interp, "sel", addEntry, 1);
  241.         Tcl_SetVar(aWindow->interp, "selection", addEntry, 1);
  242.         free(addEntry);
  243.         FsflatRedrawFile(aWindow, filePtr);
  244.         return;
  245.     }
  246.     } else {        /* group selection instead of file selection. */
  247.     /* I don't do tcl selection variable stuff with groups yet. */
  248.     /* lineP stuff doesn't make sense with groups. */
  249.     if (groupPtr->selectedP) {
  250.         /* remove it from selection */
  251.         groupPtr->selectedP = FALSE;
  252.         for (selPtr = aWindow->selectionList, backPtr = selPtr;
  253.             selPtr != NULL; selPtr = selPtr->nextPtr) {
  254.         if (selPtr->fileP) {
  255.             backPtr = selPtr;
  256.             continue;
  257.         }
  258.         if (selPtr->selected.groupPtr != groupPtr) {
  259.             backPtr = selPtr;
  260.             continue;
  261.         }
  262.         /* check if nothing is selected anymore */
  263.         if (selPtr == aWindow->selectionList) {
  264.             aWindow->selectionList = selPtr->nextPtr;
  265.             if (aWindow->selectionList == NULL) {
  266.             /*
  267.              * After the first time, Sx_SelectionSet will call
  268.              * FsflatSelChange, which calls FsflatClearWholeSelection().
  269.              * This is a warning...
  270.              */
  271.             Sx_SelectionSet(fsflatDisplay, FsflatSelFetch,
  272.                 FsflatSelChange, (ClientData) aWindow);
  273.             }
  274.         } else {
  275.             backPtr->nextPtr = selPtr->nextPtr;
  276.         }
  277.         free(selPtr);
  278.         /* not yet implemented */
  279.         FsflatRedrawGroup(aWindow, groupPtr);
  280.         break;
  281.         }
  282.     } else {
  283.         /* add it to selection */
  284.         groupPtr->selectedP = TRUE;
  285.         selPtr = (FsflatSelection *) malloc(sizeof (FsflatSelection));
  286.         selPtr->fileP = FALSE;
  287.         selPtr->lineP = FALSE;
  288.         selPtr->nextPtr = NULL;
  289.         selPtr->selected.groupPtr = groupPtr;
  290.         if (aWindow->selectionList == NULL) {
  291.         if (aWindow->selectionList == NULL) {
  292.             /*
  293.              * After the first time, Sx_SelectionSet will call
  294.              * FsflatSelChange, which calls FsflatClearWholeSelection().
  295.              * This is a warning...
  296.              */
  297.             Sx_SelectionSet(fsflatDisplay, FsflatSelFetch,
  298.                 FsflatSelChange, (ClientData) aWindow);
  299.         }
  300.         aWindow->selectionList = selPtr;
  301.         } else {
  302.         for (backPtr = aWindow->selectionList; backPtr->nextPtr != NULL;
  303.             backPtr = backPtr->nextPtr) {
  304.             /* do nothing */
  305.         }
  306.         backPtr->nextPtr = selPtr;
  307.         }
  308.         /* not yet implemented */
  309.         FsflatRedrawGroup(aWindow, groupPtr);
  310.     }
  311.     }
  312.  
  313.     return;
  314. }
  315.  
  316.  
  317.  
  318. /*
  319.  *----------------------------------------------------------------------
  320.  *
  321.  * FsflatClearWholeSelection --
  322.  *
  323.  *    Empty the selection.
  324.  *
  325.  * Results:
  326.  *    None.
  327.  *
  328.  * Side effects:
  329.  *    The selection list disappears.
  330.  *
  331.  *----------------------------------------------------------------------
  332.  */
  333. void
  334. FsflatClearWholeSelection(aWindow)
  335.     FsflatWindow    *aWindow;
  336. {
  337.     FsflatSelection    *selPtr, *nextPtr;
  338.  
  339.     for (selPtr = aWindow->selectionList; selPtr != NULL; ) {
  340.     if (selPtr->fileP) {
  341.         selPtr->selected.filePtr->selectedP = FALSE;
  342.         selPtr->selected.filePtr->lineP = FALSE;
  343.         FsflatRedrawFile(aWindow, selPtr->selected.filePtr);
  344.     } else {
  345.         selPtr->selected.groupPtr->selectedP = FALSE;
  346.         /* not yet implemented */
  347.         FsflatRedrawGroup(aWindow, selPtr->selected.groupPtr);
  348.     }
  349.     nextPtr = selPtr->nextPtr;
  350.     free(selPtr);
  351.     selPtr = nextPtr;
  352.     }
  353.     aWindow->selectionList = NULL;
  354.     Tcl_SetVar(aWindow->interp, "sel", "", 1);
  355.     Tcl_SetVar(aWindow->interp, "selection", "", 1);
  356.  
  357.     return;
  358. }
  359.  
  360.  
  361. /*
  362.  *----------------------------------------------------------------------
  363.  *
  364.  * FsflatSelFetch --
  365.  *
  366.  *    Called by the Sx selection package when someone wants to know
  367.  *    what's selected.
  368.  *
  369.  * Results:
  370.  *    The number of bytes in the fetched selection, or -1 if there's an error.
  371.  *    (See the Sx_SelectionGet() documentation.)
  372.  *
  373.  * Side effects:
  374.  *    None.
  375.  *
  376.  *----------------------------------------------------------------------
  377.  */
  378. /*ARGSUSED*/
  379. int
  380. FsflatSelFetch(clientData, askedFormat, firstByte, numBytes, valuePtr,
  381.     formatPtr)
  382.     ClientData    clientData;
  383.     char    *askedFormat;
  384.     int        firstByte;
  385.     int        numBytes;
  386.     char    *valuePtr;
  387.     char    *formatPtr;
  388. {
  389.     FsflatWindow    *aWindow;
  390.     int            number, n;
  391.     char        *space = NULL;
  392.     char        *copyString;
  393.     FsflatSelection    *tmpPtr;
  394.  
  395.     /* Use aWindow as the clientData */
  396.     aWindow = (FsflatWindow *) clientData;
  397.     strncpy(formatPtr, "text", SX_FORMAT_SIZE);
  398.     if (numBytes < 1) {
  399.     return 0;
  400.     }
  401.     if (firstByte < 0) {
  402.     return -1;
  403.     }
  404.     valuePtr[0] = '\0';
  405.  
  406.     /*
  407.      * temporary lunacy test - set number 1 less than numBytes for null char.
  408.      * this fixes stack-trashing problem, but i don't see below where I'm
  409.      * writing off the end of the buffer...
  410.      */
  411.     number = numBytes - 1;
  412.     for (tmpPtr = aWindow->selectionList; tmpPtr != NULL && number > 0;
  413.         tmpPtr = tmpPtr->nextPtr) {
  414.     Boolean    endP = FALSE;
  415.  
  416.     if (!(tmpPtr->selected.filePtr->selectedP)) {
  417.         Sx_Panic(fsflatDisplay,
  418.             "Inconsistency in selected list discovered.");
  419.     }
  420.     /*
  421.      * Here I'm assuming that if a group is selected, it won't mean
  422.      * to go through and grab all the files...  Maybe it can mean the
  423.      * matching rule or something?  Maybe I need some other selection
  424.      * mechanism for internal group selection?  Or maybe selecting a
  425.      * group is just an interface for actual selection of all the
  426.      * files in it...
  427.      */
  428.     if (!(tmpPtr->fileP)) {
  429.         Sx_Panic(fsflatDisplay, "Can't fetch group selections yet.");
  430.     }
  431.     if (tmpPtr->nextPtr == NULL) {
  432.         endP = TRUE;
  433.     }
  434.     if (tmpPtr->lineP) {
  435.         int    i;
  436.  
  437.         /*
  438.          * This is how it's done in FsflatRedrawFile() and
  439.          * the column width calculator, but the calculation should
  440.          * be centralized!
  441.          */
  442.         if (space == NULL) {
  443.         space = (char *) malloc(aWindow->maxEntryWidth + 1);
  444.         }
  445.         strcpy(space, tmpPtr->selected.filePtr->name);
  446.         for (i = strlen(space); i < aWindow->maxEntryWidth + 1;
  447.             i++) {
  448.         space[i] = ' ';
  449.         }
  450.         /*
  451.          * Put in null char so FsflatGetFileFields concatenates correctly
  452.          * at space[aWindow->maxNameLength + 2].  The 2 is for spaces
  453.          * between the name and info fields.  (Again, from
  454.          * FsflatRedrawFile().)
  455.          */
  456.         space[aWindow->maxNameLength + 2] = '\0';
  457.         FsflatGetFileFields(aWindow, tmpPtr->selected.filePtr,
  458.             &(space[aWindow->maxNameLength + 2]));
  459.         copyString = space;
  460.         n = aWindow->maxEntryWidth;
  461.     } else {
  462.         copyString = tmpPtr->selected.filePtr->name;
  463.         n = strlen(copyString);
  464.     }
  465.  
  466.     if (firstByte > 0) {
  467.         if (n <= firstByte) {
  468.         firstByte -= n;
  469.         if (!endP) {        /* for space between strings */
  470.             firstByte--;    /* may leave firstByte -= for space */
  471.         }
  472.         continue;
  473.         } else {
  474.         copyString = copyString + firstByte;
  475.         n -= firstByte;
  476.         firstByte = 0;
  477.         }
  478.     } else if (firstByte < 0) {
  479.         /* firstByte is -1 to show we must first copy a space */
  480.         number--;
  481.         firstByte = 0;
  482.         strcat(valuePtr, " ");
  483.     }
  484.     strncat(valuePtr, copyString, number);
  485.     if (number - n < 0) {
  486.         number = 0;
  487.         break;
  488.     }
  489.     number -= n;
  490.     if (number > 0 && !endP) {
  491.         strcat(valuePtr, " ");
  492.         number--;
  493.     }
  494.     }
  495.     if (space != NULL) {
  496.     free(space);
  497.     space = NULL;
  498.     }
  499.  
  500. /* temporary lunacy, -1 to avoid counting null char if not at end of buffer */
  501.     if (number == 0) {
  502.     return (numBytes - number);
  503.     } else {
  504.     return (numBytes - number - 1);
  505.     }
  506. }
  507.  
  508.  
  509.  
  510. /*
  511.  *----------------------------------------------------------------------
  512.  *
  513.  * FsflatSelChange --
  514.  *
  515.  *    Called by the Sx selection package whenever the selection changes
  516.  *    out from under us.
  517.  *
  518.  * Results:
  519.  *    None.
  520.  *
  521.  * Side effects:
  522.  *    The list of selected nodes is cleared.
  523.  *
  524.  *----------------------------------------------------------------------
  525.  */
  526. void
  527. FsflatSelChange(clientData)
  528.     ClientData    clientData;
  529. {
  530.     FsflatWindow    *aWindow;
  531.  
  532.     aWindow = (FsflatWindow *) clientData;
  533.     FsflatClearWholeSelection(aWindow);
  534.  
  535.     return;
  536. }
  537.  
  538.  
  539. /*
  540.  *----------------------------------------------------------------------
  541.  *
  542.  * FsflatHighlightMovement
  543.  *
  544.  *    Highlight mouse movement to show what file the cursor is over.
  545.  *
  546.  * Results:
  547.  *    None.
  548.  *
  549.  * Side effects:
  550.  *    The display changes.
  551.  *
  552.  *----------------------------------------------------------------------
  553.  */
  554. void
  555. FsflatHighlightMovement(window, eventPtr)
  556.     Window        window;
  557.     XPointerMovedEvent    *eventPtr;
  558. {
  559.     FsflatFile    *filePtr;
  560.     FsflatFile    *last_filePtr = NULL;
  561.     static    int    oldx = -1;    /* Coordinates outside window. */
  562.     static    int    oldy = -1;
  563.     int        x, y;
  564.     FsflatWindow    *aWindow;
  565.  
  566.     if (eventPtr->type != MotionNotify && eventPtr->type != LeaveNotify) {
  567.     return;
  568.     }
  569.     if (XFindContext(fsflatDisplay, window, fsflatWindowContext,
  570.         (caddr_t) &aWindow) != 0) {
  571.     Sx_Panic(fsflatDisplay, "Fstree didn't recognize given window.");
  572.     }
  573.  
  574.     /* event was selected in display window, so coordinates are ok */
  575.     x = ((XButtonEvent *) eventPtr)->x;
  576.     y = ((XButtonEvent *) eventPtr)->y;
  577.  
  578.     if (eventPtr->type != LeaveNotify) {
  579.     filePtr = FsflatMapCoordsToFile(aWindow, x, y);
  580.     } else {
  581.     filePtr = NULL;
  582.     }
  583.     last_filePtr = FsflatMapCoordsToFile(aWindow, oldx, oldy);
  584.  
  585.     if (filePtr == last_filePtr) {    /* leave highlighting alone */
  586.     oldx = x;
  587.     oldy = y;
  588.     return;
  589.     }
  590.     
  591.     /*
  592.      * If we've already toggled a node before, re-toggle it to turn it off
  593.      * as we move away from it.
  594.      */
  595.     if (last_filePtr != NULL) {
  596.     /* I used to toggle highlighting here rather than just turn it off. */
  597.     last_filePtr->highlightP = FALSE;
  598.     FsflatRedrawFile(aWindow, last_filePtr);
  599.     oldx = oldy = -1;    /* Set to coordinates outside window */
  600.     }
  601.  
  602.     /*
  603.      * If no new file, do nothing.
  604.      */
  605.     if (filePtr == NULL) {
  606.     return;
  607.     }
  608.  
  609.  
  610.     /*
  611.      * toggle new file.
  612.      */
  613.     /*
  614.      * I used to toggle highlighting here rather than just turn it on,
  615.      * but now I don't do selection by toggling, so I needn't here either.
  616.      */
  617.     filePtr->highlightP = TRUE;
  618.     FsflatRedrawFile(aWindow, filePtr);
  619.     oldx = x;
  620.     oldy = y;
  621.  
  622.     return;
  623. }
  624.